package com.csot.service;

import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import com.csot.model.CityIp;
import com.csot.model.CitySegment;
import com.csot.model.TotalSegment;
import com.jfinal.plugin.activerecord.Db;
import com.jfinal.plugin.activerecord.Record;
import com.jfinal.plugin.ehcache.CacheKit;
import com.csot.common.utils.StringUtils;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.map.BiMap;

@Service
public class IndexService implements Runnable {

	private static final Logger log = LoggerFactory.getLogger(IndexService.class);

	CitySegment csDao = new CitySegment().dao();
	TotalSegment tsDao = new TotalSegment().dao();
	CityIp ciDao = new CityIp().dao();
	
	@Override
	public void run() {
		// TODO Auto-generated method stub
		refresh();
	}
	
	/*
	 * 刷新缓存
	 */
	public void refresh() {
		handleTotal();
		handleUse();
		handleCityTotal();
		handleCityUse();
		handleUse_On();
		handleUse_Off();
	}
	
	public Map<String, Long> cTotal(Map<String, List<TotalSegment>> tMap, String city) {
		Map<String, Long> totalMap = new HashMap<>();
		BiMap<String, String> map = CacheKit.get("dict-data", "ip_type");
		if (map != null) {
			map.forEach((k, v) -> {
				if(CollUtil.isEmpty(tMap.get(k))) {
					totalMap.put(k, 0L);
				} else {
					for(Map.Entry<String, List<TotalSegment>> entry : tMap.entrySet()){
						long i = 0L;
						List<TotalSegment> list = entry.getValue();
						if(StringUtils.isNotBlank(city)) {
							list = list.stream().filter(f -> city.equals(f.getIpCity())).collect(Collectors.toList());
						}
						for(TotalSegment bean : list) {
							i += bean.getIpEndI() - bean.getIpStartI();
						}
						totalMap.put(entry.getKey(), i);
					}
				}
			});
		}
		return totalMap;
	}
	
	public Map<String, Long> cUse(Map<String, List<CitySegment>> uMap, String city) {
		Map<String, Long> useMap = new HashMap<>();
		BiMap<String, String> map = CacheKit.get("dict-data", "ip_type");
		if (map != null) {
			map.forEach((k, v) -> {
				if(CollUtil.isEmpty(uMap.get(k))) {
					useMap.put(k, 0L);
				} else {
					for(Map.Entry<String, List<CitySegment>> entry : uMap.entrySet()){
						long i = 0L;
						List<CitySegment> list = entry.getValue();
						if(StringUtils.isNotBlank(city)) {
							list = list.stream().filter(f -> city.equals(f.getIpCity())).collect(Collectors.toList());
						}
						for(CitySegment bean : list) {
							i += bean.getIpEndI() - bean.getIpStartI();
						}
						useMap.put(entry.getKey(), i);
					}
				}
			});
		}
		return useMap;
	}
	
	public Map<String, Long> cUse_On_Off(Map<String, List<CityIp>> oMap, String city) {
		Map<String, Long> useMap = new HashMap<>();
		BiMap<String, String> map = CacheKit.get("dict-data", "ip_type");
		if (map != null) {
			map.forEach((k, v) -> {
				if(CollUtil.isEmpty(oMap.get(k))) {
					useMap.put(k, 0L);
				} else {
					for(Map.Entry<String, List<CityIp>> entry : oMap.entrySet()){
						long i = 0L;
						List<CityIp> list = entry.getValue();
						if(StringUtils.isNotBlank(city)) {
							list = list.stream().filter(f -> city.equals(f.getIpCity())).collect(Collectors.toList());
						}
						for(CityIp bean : list) {
							i += bean.getIpAddressI();
						}
						useMap.put(entry.getKey(), i);
					}
				}
			});
		}
		return useMap;
	}
	
	public Map<String, Long> cCityTotal(Map<String, List<TotalSegment>> cMap) {
		Map<String, Long> cityMap = new HashMap<>();
		BiMap<String, String> map = CacheKit.get("dict-data", "ip_city");
		if (map != null) {
			map.forEach((k, v) -> {
				if(CollUtil.isEmpty(cMap.get(k))) {
					cityMap.put(k, 0L);
				} else {
					long i = 0L;
					for(TotalSegment bean : cMap.get(k)) {
						i += bean.getIpEndI() - bean.getIpStartI();
					}
					cityMap.put(k, i);
				}
			});
		}
		return cityMap;
	}
	
	public Map<String, Long> cCityUse(Map<String, List<CityIp>> cMap) {
		Map<String, Long> cityMap = new HashMap<>();
		BiMap<String, String> map = CacheKit.get("dict-data", "ip_city");
		if (map != null) {
			map.forEach((k, v) -> {
				if(CollUtil.isEmpty(cMap.get(k))) {
					cityMap.put(k, 0L);
				} else {
					long i = 0L;
					for(CityIp bean : cMap.get(k)) {
						i += bean.getIpAddressI();
					}
					cityMap.put(k, i);
				}
			});
		}
		return cityMap;
	}
	
	// 上图-所有
	public Map<String, List<TotalSegment>> handleTotal() {
		List<TotalSegment> tList = getTotal();
		Map<String, List<TotalSegment>> tMap = tList.stream().collect(Collectors.groupingBy(TotalSegment::getIpType));
		CacheKit.put("index-data", "total-segment", tMap);
		return tMap;
	}
	
	// 上图-使用
	public Map<String, List<CityIp>> handleUse() {
		List<Record> fList = getUseIp();
		List<CityIp> cityList = fList.stream().map(m -> {
					CityIp ip = new CityIp();
					ip.setIpAddressI(m.getLong("num"));
					ip.setIpStatus(m.getStr("ip_status"));
					ip.setIpType(m.getStr("ip_type"));
					ip.setIpCity(m.getStr("ip_city"));
					return ip;
				}).collect(Collectors.toList());
		
		Map<String, List<CityIp>> nMap = cityList.stream().collect(Collectors.groupingBy(CityIp::getIpType));
		
		CacheKit.put("index-data", "use-segment", nMap);
		return nMap;
	}
	
	// 上图-使用-on
	public Map<String, List<CityIp>> handleUse_On() {
		List<Record> fList = getUseIp();
		List<CityIp> cityList = fList.stream().filter(f -> "on".equals(f.getStr("ip_status")))
				.map(m -> {
					CityIp ip = new CityIp();
					ip.setIpAddressI(m.getLong("num"));
					ip.setIpStatus(m.getStr("ip_status"));
					ip.setIpType(m.getStr("ip_type"));
					ip.setIpCity(m.getStr("ip_city"));
					return ip;
				}).collect(Collectors.toList());
		
		Map<String, List<CityIp>> nMap = cityList.stream().collect(Collectors.groupingBy(CityIp::getIpType));
		
		CacheKit.put("index-data", "on-segment", nMap);
		return nMap;
	}
	
	// 上图-使用-off
	public Map<String, List<CityIp>> handleUse_Off() {
		List<Record> fList = getUseIp();
		List<CityIp> cityList = fList.stream().filter(f -> "off".equals(f.getStr("ip_status")) || StringUtils.isBlank(f.getStr("ip_status")))
				.map(m -> {
					CityIp ip = new CityIp();
					ip.setIpAddressI(m.getLong("num"));
					ip.setIpStatus(m.getStr("ip_status"));
					ip.setIpType(m.getStr("ip_type"));
					ip.setIpCity(m.getStr("ip_city"));
					return ip;
				}).collect(Collectors.toList());
		
		Map<String, List<CityIp>> nMap = cityList.stream().collect(Collectors.groupingBy(CityIp::getIpType));
		
		CacheKit.put("index-data", "off-segment", nMap);
		return nMap;
	}
	
	// 下图-城市-全部
	public Map<String, List<TotalSegment>> handleCityTotal() {
		List<TotalSegment> tList = getTotal();
		Map<String, List<TotalSegment>> cMap = tList.stream().collect(Collectors.groupingBy(TotalSegment::getIpCity));
		CacheKit.put("index-data", "city-total-segment", cMap);
		return cMap;
	}
	
	// 下图-城市-使用
	public Map<String, List<CityIp>> handleCityUse() {
		List<Record> fList = getUseIp();
		List<CityIp> cityList = fList.stream().map(m -> {
					CityIp ip = new CityIp();
					ip.setIpAddressI(m.getLong("num"));
					ip.setIpStatus(m.getStr("ip_status"));
					ip.setIpType(m.getStr("ip_type"));
					ip.setIpCity(m.getStr("ip_city"));
					return ip;
				}).collect(Collectors.toList());
		
		Map<String, List<CityIp>> nMap = cityList.stream().collect(Collectors.groupingBy(CityIp::getIpCity));
		CacheKit.put("index-data", "city-use-segment", nMap);
		return nMap;
	}

	private List<TotalSegment> getTotal() {

		String sql = "select * from  t_total_segment ";

		return tsDao.find(sql);
	}
	
	private List<CitySegment> getUse() {

		String sql = "select * from  t_city_segment ";

		return csDao.find(sql);
	}

	private List<Record> getUseIp() {
		String sql = "select count(1) as num, ip_type, ip_city, ip_status "
				+ " from t_city_ip "
				+ " group by ip_type ,ip_city ,ip_status ";
		return Db.find(sql);
	}
	
	public Map<String, Long> orderBy(Map<String, Long> map) {
		Map<String, Long> resultMap = new LinkedHashMap<String, Long>();
		List<Map.Entry<String, Long>> list = new LinkedList<Map.Entry<String, Long>>(map.entrySet());
		Collections.sort(list, new Comparator<Map.Entry<String, Long>>() {
            public int compare(Map.Entry<String, Long> o1,
                    Map.Entry<String, Long> o2) {
                return getOrder(o1.getKey()) - getOrder(o2.getKey());
            }
        });
		for (Map.Entry<String, Long> entry : list) {
			resultMap.put(entry.getKey(), entry.getValue());
        }
		return resultMap;
	}
	
	private int getOrder(String city) {
		int res = 0;
		switch(city) {
        case "sy":
        	res = 1;
            break;
        case "dl":
        	res = 2;
            break;
        case "as":
        	res = 3;
            break;
        case "tl":
        	res = 4;
            break;
        case "bx":
        	res = 5;
            break;
        case "dd":
        	res = 6;
            break;
        case "jz":
        	res = 7;
            break;
        case "fs":
        	res = 8;
            break;
        case "yk":
        	res = 9;
            break;
        case "fx":
        	res = 10;
            break;
        case "ly":
        	res = 11;
            break;
        case "pj":
        	res = 12;
            break;
        case "cy":
        	res = 13;
            break;
        case "hld":
        	res = 14;
            break;
        case "sbj":
        	res = 15;
            break;
        default:
        	res = 99;
            break;
        }
		return res;
	}

}
